﻿using Novice.Units;
using System.Collections.Generic;
using System.Linq;

namespace Novice.Calories
{
    public class Label
    {
        #region private data

        private readonly string _name;
        private readonly NutritionFacts _facts;
        private readonly Recipe _recipe;

        #endregion

        public Label(string name = "")
        {
            _name = name;
            _facts = new NutritionFacts();
            _recipe = new Recipe();
        }

        public string Name
        {
            get { return _name; }
        }
        public NutritionFacts Facts
        {
            get { return _facts; }
        }
        public ValueWithUnit ServingSize { get; set; }
        public Recipe Recipe
        {
            get { return _recipe; }
        }
    }

    public struct FactsWithAmount
    {
        public NutritionFacts Facts { get; set; }
        public ValueWithUnit Amount { get; set; }
    }

    public class TraverseEnumerator: IEnumerator<Product>
    {
        struct Context
        {
            public IEnumerator<Product> Enumerator;
            public double Coefficient;
        }

        #region private data

        private readonly Stack<Context> _stack;
        private Product _currentProduct;

        #endregion

        public TraverseEnumerator(IEnumerator<Product> root)
        {
            _currentProduct = null;
            _stack = new Stack<Context>();
            _stack.Push(new Context
                        {
                            Enumerator = root,
                            Coefficient = 1.0
                        });
        }

        public Product Current
        {
            get { return _currentProduct; }
        }

        public void Dispose()
        {
            Dispose(true);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposing) return;

            foreach (var context in _stack)
                context.Enumerator.Dispose();
        }

        object System.Collections.IEnumerator.Current
        {
            get { return _currentProduct; }
        }

        public bool MoveNext()
        {
            while(_stack.Count > 0)
            {
                var context = _stack.Peek();
                var enumerator = context.Enumerator;

                while(enumerator.MoveNext())
                {
                    var product = enumerator.Current;
                    var label = product.Label;
                    var recipe = label.Recipe;

                    var amount = product.Amount;
                    var outcome = recipe.Outcome;

                    var newContext = new Context
                                     {
                                         Enumerator = product.Label.Recipe.Products.GetEnumerator(),
                                         Coefficient = amount.Value/outcome.GetAs(amount.Unit)
                                     };

                    _stack.Push(newContext);
                    
                    context = newContext;
                }
                _stack.Pop();

                // visit
            }
        }

        public void Reset()
        {
            var rootContext = _stack.First();
        }
    
    public static class LabelExtensions
    {
        public static FactsWithAmount GetNutritionFacts(this Label label)
        {
            foreach (var VARIABLE in enumerable)
            {
                
            }
        }

        public static IEnumerable<Product> GetSummary(this Label label)
        {
            
        }
    }
}
